package com.iot08.api.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iot08.api.config.redis.RedisClusterService;
import com.iot08.api.controller.base.BaseController;
import com.iot08.api.service.DeviceService;
import com.iot08.api.service.supplement.KafkaService;
import com.iot08.api.utils.ExcelUtil;
import com.iot08.api.utils.SpringContextUtil;
import com.iot08.api.vo.request.AddRelatedDeviceReqVO;
import com.iot08.common.constant.ConstCacheField;
import com.iot08.common.constant.ConstKafka;
import com.iot08.common.entity.app.Device;
import com.iot08.common.response.Response;
import com.iot08.common.utils.StringUtil;
import com.iot08.common.utils.response.ResponseEnum;
import com.iot08.common.utils.response.ResponseMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

/**
 * @version 1.0
 * @Description: 后台管理调用的接口
 * @time: 2021/3/15 17:07
 * @author: Rock
 */
@Slf4j
@RestController
@RequestMapping("getway")
public class AdminController extends BaseController {

    @Resource
    private DeviceService deviceService;

    @Resource
    private RedisClusterService redisClusterService;

    @Resource
    private KafkaService kafkaService;

    /**
     * @param imei
     * @time: 2021/3/15 17:16
     * @author: Rock
     * @version 1.0
     */
    @PostMapping("/reset/{imei}")
    public ResponseMap reset(@PathVariable("imei") String imei ,String params,HttpServletRequest request) {
        if(!isInside(request)){
            return ResponseMap.fail();
        }
        JSONObject paramsMap = getParameter(request);

        Boolean isLossDevUnbindOption = paramsMap.getBoolean("isLossDevUnbindOption");
        String operator = paramsMap.getString("operator");
        String vender = paramsMap.getString("vender");
        if(vender == null){
            return ResponseMap.fail("vender miss");
        }
        String activeProfile = SpringContextUtil.getActiveProfile();
        if("dev".contains(activeProfile) || "local".contains(activeProfile)){
            //测试环境 打印日志
            log.info("web后台恢复出厂设置:imei:{} 参数:{}", imei, paramsMap.toJSONString());
        }
        if (StringUtil.isNotBlank(imei)) {
            Device device = deviceService.findById(imei);
            if (device != null) {

                if(device.getLossDevStatus() == 1 && !isLossDevUnbindOption){
                    log.info("imei:{} 解绑失败,设备已被挂失", imei);
                    return ResponseMap.fail(ResponseEnum.STATUS6001.getCode(), ResponseEnum.STATUS6001.getMsg());
                }
                //是否是和对应的厂商编号匹配
                if(!vender.equalsIgnoreCase("8888")){
                    //不是超级管理员需要 匹配设备的厂商编号
                    if(!String.valueOf(device.getAgent()).equalsIgnoreCase(vender)){
                        log.error("web调用恢复出厂设置,厂商vender标识不对 imei:{} 的厂商vender:{}, web调用的厂商Vender:{}",
                                device.getId(), device.getAgent(), vender);
                        return ResponseMap.fail("无权限解绑");
                    }
                }
                deviceService.reset(device, operator, "web");
            }
        }
        return ResponseMap.success();
    }

    /**
     * @param request 请求对象
     * @time: 2021/3/15 17:16
     * @author: Rock
     * @version 1.0
     */
    @PostMapping("/reset/many_reset")
    public ResponseMap many_reset(String params, HttpServletRequest request) {
        if(!isInside(request)){
            return ResponseMap.fail();
        }
        JSONObject paramsMap = getParameter(request);
        String activeProfile = SpringContextUtil.getActiveProfile();
        if("dev".contains(activeProfile) || "local".contains(activeProfile)){
            //测试环境 打印日志
            log.info("web后台 多个 恢复出厂设置: 参数:{}", paramsMap.toJSONString());
        }


        String operator = paramsMap.getString("operator");
        String vender = paramsMap.getString("vender");
        if(vender == null){
            return ResponseMap.fail("vender miss");
        }
        String failFilePath = paramsMap.getString("failFilePath");
        JSONArray resetImeiList = paramsMap.getJSONArray("resetImeiList");
        if(resetImeiList == null){
            String filePath = paramsMap.getString("filePath");
            if(filePath == null){
                return ResponseMap.fail("filePath miss");
            }
            //读列表文件,拿到imei 列表
            try {
                Workbook imeiListFile = WorkbookFactory.create(Files.newInputStream(Paths.get(filePath)));
//                Workbook imeiListFile = new XSSFWorkbook(filePath);
                if (imeiListFile != null && imeiListFile.getSheetAt(0) != null) {
                    Sheet sheet = imeiListFile.getSheetAt(0);
                    int countRow = sheet.getPhysicalNumberOfRows();
//                    if (countRow > 1000) {
//                        return Response.fail("文件不能超过1000个号码");
//                    }
                    Set<String> set = ExcelUtil.getImei(sheet);
                    resetImeiList = new JSONArray();
                    resetImeiList.addAll(set);
                    if("dev".contains(activeProfile) || "local".contains(activeProfile)){
                        //测试环境 打印日志
                        log.info("web后台 多个 恢复出厂设置: resetImeiList:{}", resetImeiList.toJSONString());
                    }
                }else{
                    return ResponseMap.fail("read filePath fail");
                }
            } catch (IOException e) {
                log.error("read filePath fail:"+e.getMessage(), e);
                return ResponseMap.fail("read filePath fail");
            } catch (InvalidFormatException e) {
                throw new RuntimeException(e);
            }


        }

        if(resetImeiList != null){
            JSONArray failImeis = new JSONArray();
            JSONArray failToLossDevImeis = new JSONArray();
            for (Object item: resetImeiList) {
                String itemStr = (String)item;
                try {
                    if (StringUtil.isNotBlank(itemStr)) {
                        Device device = deviceService.findById(itemStr);
                        if (device != null) {
                            if(device.getLossDevStatus() == 1){
                                log.info("imei:{} 解绑失败,设备已被挂失", itemStr);
                                failToLossDevImeis.add(itemStr);
                                continue;
                            }
                            //是否是和对应的厂商编号匹配
                            if(!vender.equalsIgnoreCase("8888")){
                                //不是超级管理员需要 匹配设备的厂商编号
                                if(!String.valueOf(device.getAgent()).equalsIgnoreCase(vender)){
                                    log.error("web调用恢复出厂设置,厂商vender标识不对 imei:{} 的厂商vender:{}, web调用的厂商Vender:{}",
                                            device.getId(), device.getAgent(), vender);
                                    failImeis.add(itemStr);
                                    continue;
                                }
                            }
                            deviceService.reset(device, operator, "web");
                        }else{
                            failImeis.add(itemStr);
                        }
                    }
                }catch (Exception error){
                    log.error("many_reset 报错:"+error.getMessage(), error);
                    failImeis.add(itemStr);
                }
            }
            JSONObject tempMap = new JSONObject();
            if(!failImeis.isEmpty()){
                tempMap.put("failImeis", failImeis.toJSONString());
            }
            if(!failToLossDevImeis.isEmpty()){
                //因挂失 失败的
                tempMap.put("failToLossDevImeis", failToLossDevImeis.toJSONString());
            }

            tempMap.put("failNum", failImeis.size());
            tempMap.put("failList", failImeis.toJSONString());
            tempMap.put("successNum", resetImeiList.size()- failImeis.size());

            if (!failImeis.isEmpty()) {
                //没有删除的
                Workbook failImeiExcel = new XSSFWorkbook();
                Sheet failImeiSheet = failImeiExcel.createSheet();
                int index = 0;
                for (int i = 0; i < failImeis.size(); i++) {
                    String item = failImeis.getString(i);
                    Row row = failImeiSheet.createRow(index);
                    Cell cell = row.createCell(0);
                    ExcelUtil.setCellValue(cell, item);
                    index++;
                }
                String filename = operator+ "_" + "resetFailList_new.xlsx";
                failFilePath = failFilePath +"/"+ filename;
                try {
//                    log.info("保存重置 失败文件 : failFilePath:{}", failFilePath);
                    FileOutputStream notDelFile = new FileOutputStream(failFilePath);
                    failImeiExcel.write(notDelFile);
//                    log.info("保存重置 失败文件 : notDelFile:{}", notDelFile);
                    notDelFile.close();


                }catch (Exception e){
                    log.error("保存恢复出厂设置失败的imei列表, 可供下载的文件时错误:"+e.getMessage(), e);
                }

            }

            return ResponseMap.success(tempMap);

        }else{
            return ResponseMap.fail();
        }

    }


    /**
     * @description 管理平台定位控制
     * @author
     * @param [request]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/6/13 10:40
     **/
    @PostMapping("/admin/internal/deviceControl")
    public ResponseMap deviceControl(HttpServletRequest request) {
        JSONObject paramsMap = getParameter(request);
        log.info("CMS 根据IMEI号下发一次定位信息 paramsMap:{} IP:{}", paramsMap, getRemortIP());
        //判断是否内部调用
        if(!isInside(request)){
            return ResponseMap.fail("not inside");
        }
        //imei
        String imei = paramsMap.getString("imei");
        //operator
        Integer operator = paramsMap.getInteger("operator");
        //accountId
        String accountId = paramsMap.getString("accountId");
        //account
        String account = paramsMap.getString("account");

        // 下发一次主动定位
        String onlineStatus = redisClusterService.hget(imei, ConstCacheField.ONLINE_STATUS);
        if (!"1".equals(onlineStatus)) {
            log.info("CMS 内部 接口下发一次主动定位 imei:{} 成功", imei);
            return ResponseMap.fail(ResponseEnum.STATUS5001.getCode(), ResponseEnum.STATUS5001.getMsg());
        }
        JSONObject kafkaJson = new JSONObject();
        String cmdType = ConstKafka.DEVICE_TYPE_RequestLocation;
        if(operator == 0){
            //定位
            cmdType = ConstKafka.DEVICE_TYPE_RequestLocation;
        }else if(operator == 1){
            //关机
            cmdType = ConstKafka.DEVICE_TYPE_PowerOff;
        } else if(operator == 2) {
            cmdType = ConstKafka.DEVICE_TYPE_REQUEST_EXCHANGE_UNBIND;
            kafkaJson.put("openCloseStatus","0");
        }
        //kafkaService.emitDeviceDemand(imei, cmdType, null, "CMS:"+accountId);
        kafkaService.emitDeviceDemand(imei, cmdType, kafkaJson, "CMS:"+accountId);
        JSONObject res = new JSONObject();
        res.put("msg", "imei:"+imei+" 远程下发主动定位成功");
        res.put("imei", imei);
        log.info("CMS 内部 接口下发一次主动定位 imei:{} 成功", imei);
        return ResponseMap.success(res);
    }

    /**
     * @description 切换ip
     * @author cwj
     * @param [request]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/6/13 10:33
     **/
    @PostMapping("/admin/internal/changeIpPort")
    public ResponseMap changeDevicePushDataIp(HttpServletRequest request) {
        JSONObject paramsMap = getParameter(request);
        log.info("CMS 根据IMEI号切换IP paramsMap:{} IP:{}", paramsMap, getRemortIP());
        //判断是否内部调用
        if(!isInside(request)){
            return ResponseMap.fail("not inside");
        }
        //imei
        String imei = paramsMap.getString("imei");
        //ip
        String ip = paramsMap.getString("ip");
        //port
        String port = paramsMap.getString("port");
        //accountId
        String accountId = paramsMap.getString("accountId");
        // 下发一次主动定位
        String onlineStatus = redisClusterService.hget(imei, ConstCacheField.ONLINE_STATUS);
        if (!"1".equals(onlineStatus)) {
            log.info("CMS 内部 切换设备推送地址 imei:{} 成功", imei);
            return ResponseMap.fail(ResponseEnum.STATUS5001.getCode(), "设备可能关机、欠费或处于弱信号环境");
        }
        JSONObject kafkaJson = new JSONObject();
        kafkaJson.put("ip",ip);
        kafkaJson.put("port",port);
        kafkaService.emitDeviceDemand(imei, ConstKafka.DEVICE_TYPE_REQUEST_CHANGE_ADDR, kafkaJson, "CMS:"+accountId);
        return ResponseMap.success();
    }


    /**
     * 判断是否是内部请求的
     * @param request
     * @return
     */
    private boolean isInside(HttpServletRequest request){
        JSONObject headerOB = new JSONObject();
//        log.info("判断是否是内部请求的: request.getHeader(\"host\"):{} header:{}", request.getHeader("host"), request.getHeaderNames());
        if(request.getHeader("host").contains(":8096")){
            return true;
        }
        return false;
    }

    private JSONObject getParameter( HttpServletRequest request) {
        Enumeration<String> parameterNames = request.getParameterNames();
        JSONObject jsonObject = new JSONObject();
        if(parameterNames.hasMoreElements()){
            // 获取URL的传参
            while (parameterNames.hasMoreElements()){
                String key = parameterNames.nextElement();
                jsonObject.put(key, request.getParameter(key));
            }
        }else{
            // 获取body的传参
            try {
                String reader = getAllRequestParam2(request);
                if(reader.length()>1){
                    if(reader.substring(0,1).equals("[")){

                    }else{
                        JSONObject tempOB = JSONObject.parseObject(reader);
                        jsonObject.putAll(tempOB);
                    }
                }

            } catch (Exception e) {
                log.error("获取参数错误"+e.getMessage(),e);
            }
        }

        return jsonObject;
    }

    public static String getAllRequestParam2(HttpServletRequest request) throws IOException {
        BufferedReader br = request.getReader();
        String str;
        StringBuilder wholeStr = new StringBuilder();
        while((str = br.readLine()) != null){
            wholeStr.append(str);
        }
        return wholeStr.toString();
    }

}
